﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using AutoMapper;
using Common.ORM.Repository;
using FreeRedis;
using Masuit.Tools;
using Masuit.Tools.Linq;
using sixgod.Common;
using sixgod.Common.Extension;
using sixgod.Common.Model;
using sixgod.Dtos.System;
using sixgod.Dtos.System.Search;
using sixgod.Enum.System;
using sixgod.Model.Attribute;
using sixgod.Model.System.Menu;
using sixgod.Service.Dictionary;
using SqlSugar;

namespace sixgod.Service.System.Implementation
{
    [Di(typeof(IMenuService))]
    public class MenuService:Repository<SystemMenu>,IMenuService
    {
        private ISqlSugarClient _db;
        private IMapper _mapper;
        private RedisClient _redisClient;
        /// <summary>Initializes a new instance of the <see cref="T:System.Object" /> class.</summary>
        public MenuService(ISqlSugarClient db,IMapper mapper, RedisClient redisClient): base(redisClient, db)
        {
            _db = db;
            _mapper = mapper;
            _redisClient = redisClient;
        }

        private void InitTestData()
        {
            SystemMenu m0 = new SystemMenu();
            m0.Order = 0;
            m0.Name="系统管理";
            m0.ParentCode = null;
            

            SystemMenu m1 = new SystemMenu();
            m1.Order = 0;
            m1.Name="用户管理";
            m1.ParentCode = "System";
            m1.Route = "1234";
            

            SystemMenu m2 = new SystemMenu();
            m2.Order = 1;
            m2.Name = "公司管理";
            m2.ParentCode = null;
            m2.Route = "123";

            m0.ComponentRoute = "64";
            m1.ComponentRoute = "64";
            m2.ComponentRoute = "64";

            m0.PermissionCode = "system";
            m1.PermissionCode = "system:menu";
            m2.PermissionCode = "company";

            m0.Type = MenuTypeEnum.Catalog;
            m1.Type = MenuTypeEnum.Menu;
            m2.Type = MenuTypeEnum.Menu;

            m0.Create("admin");
            m1.Create("admin");
            m2.Create("admin");
            
            var s = InsertRange(new[]{m0,m1,m2});
            if (s)
            {
                
            }
        }

        public void Init()
        {
            InitTestData();
        }

        /// <summary>
        /// 获取所有列表
        /// </summary>
        /// <returns></returns>
        public async Task<List<SystemMenu>> GetAllList()
        {
            var str = await _redisClient.GetAsync(CacheKeyConsts.MENU_LIST);
            if (str == null)
            {
                var list = await GetListAsync(r=>r.IsDelete==0);
                await _redisClient.SetAsync(CacheKeyConsts.MENU_LIST,list.ToJsonString(),3600*24);
                return list;
            }
            return str.ToObj<List<SystemMenu>>();
        }


        public async Task<PageResponseResult<MenuDto>> GetPageList(MenuPageSearch search)
        {
            var list = await GetAllList();
            List<MenuDto> result = new List<MenuDto>();

            Expression<Func<SystemMenu,bool>> exp = r=>r.ParentCode.IsNullOrEmpty();
            if (!search.MenuName.IsNullOrEmpty())
            {
                exp.And(r=>r.Name.Contains(search.MenuName));
            }

            var systemMenus = list.Where(exp.Compile())
                .OrderBy(r=>r.Order).Skip(search.Skip()).Take(search.PageSize);

            result.AddRange(_mapper.Map<List<MenuDto>>(systemMenus));

            foreach (var item in result)
            {
                item.CheckChildren(list);
            }

            return new PageResponseResult<MenuDto>(){Data=result,Count = list.Count(exp.Compile())};
        }


        public async Task<List<MenuDto>> GetChildrenMenu(string code)
        {
            var list = await GetAllList();
            var result = _mapper.Map<List<MenuDto>>(list.Where(r => r.ParentCode == code));
            foreach (var item in result)
            {
                item.CheckChildren(list);
            }

            return result;
        }

        /// <summary>
        /// 带层级的所有列表
        /// </summary>
        /// <returns></returns>
        public async Task<List<MenuDto>> GetAllListForSelect()
        {
            var list = await GetAllList();
            List<MenuDto> result = new List<MenuDto>();
            result.AddRange(_mapper.Map<List<MenuDto>>(list.Where(r => r.ParentCode.IsNullOrEmpty())));

            foreach (var item in result)
            {
                var menu2 = _mapper.Map<List<MenuDto>>(list.Where(r => r.ParentCode == item.Code));
                foreach (var item2 in menu2)
                {
                    item2.ChildMenus = _mapper.Map<List<MenuDto>>(list.Where(r=>r.ParentCode == item2.Code));
                }
                item.ChildMenus = menu2;
            }

            return result;
        }

        /// <summary>
        /// 根据用户ID获取菜单
        /// </summary>
        /// <param name="loginUid"></param>
        /// <returns></returns>
        public async Task<List<MenuDto>> GetUserMenu(string loginUid)
        {
            var list = await GetAllList();
            // todo 用户筛选
            List<MenuDto> result = new List<MenuDto>();
            result.AddRange(_mapper.Map<List<MenuDto>>(list.Where(r => r.ParentCode.IsNullOrEmpty())));

            foreach (var item in result)
            {
                var menu2 = _mapper.Map<List<MenuDto>>(list.Where(r => r.ParentCode == item.Code));
                if (menu2.Count==0)
                {
                    item.ChildMenus = null;
                }
                item.ChildMenus = menu2;
            }

            return result;
        }

        #region 修改

        public async Task<bool> Save(SystemMenu data)
        {
            if (data.Id.IsNullOrEmpty())
            {
                // add
                data.Format();
                data.Create("admin");;
                await _redisClient.DelAsync(CacheKeyConsts.MENU_LIST);
                return await InsertAsync(data);
            }
            else
            {
                // update
                data.Update("admin");
                await _redisClient.DelAsync(CacheKeyConsts.MENU_LIST);
                return await _db.Updateable<SystemMenu>(data).Where(r=>r.Id == data.Id).ExecuteCommandHasChangeAsync();
            }
            
        }

        public async Task<int> Delete(string Id)
        {
            await _redisClient.DelAsync(CacheKeyConsts.MENU_LIST);
            return await _db.Updateable<SystemMenu>()
                .SetColumns(r=>new SystemMenu(){IsDelete = 1,UpdateTime = DateTime.Now,UpdateUser = "admin"})
                .Where(r=>r.Id==Id)
                .ExecuteCommandAsync();
        }

        #endregion
    }



}
